package springcloud.controller;


import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import springcloud.entity.Member;
import springcloud.entity.Result;

import javax.annotation.Resource;
import java.util.List;


@SuppressWarnings("all")
@RestController
@Slf4j
public class MemberConsumerController {

    //装配RestTemplate对象，用于调用provider提供的接口
    @Resource
    private RestTemplate restTemplate;
    //装配DiscoveryClient对象，用于获取服务提供方[集群]的名称
    @Resource
    private DiscoveryClient discoveryClient;

    //定义member_service_provider_url 这是一个基础url地址。可用来后续进行拼接
    //使用shift+ctrl+u 进行字母大小写的切换
    /**
     * 老师说明:
     * 1. MEMBER-SERVICE-PROVIDER 就是服务提供方[集群], 注册到 Eureka Server 的名称
     * 2. 也是服务提供方[集群]对外暴露的名称为 MEMBER-SERVICE-PROVIDER
     * 3. MEMBER-SERVICE-PROVIDER 目前有 两个 Availability Zones 即member-service-provider:10000
     *    和 member-service-provider:10002
     *    需要增加一个注解 @LoadBalanced 赋予 RestTemplate 负载均衡的能力。也就是会根据你的负载均衡算法
     *    来选择某个服务去访问, 默认是轮询算法, 当然我们也可以自己配置负载均衡算法
     */
    private static final String MEMBER_SERVICE_PROVIDER_URL = "http://MEMBER-SERVICE-PROVIDER";


    //定义一个方法，获取 Eureka Server 服务注册信息
    @GetMapping("/member/consumer/discovery")
    public Object discovery() {
        //得到服务列表
        List<String> services = discoveryClient.getServices();
        //遍历服务列表
        for (String service : services) {
            log.info("服务名:{}", service);
            //得到服务实例列表
            List<ServiceInstance> instances = discoveryClient.getInstances(service);
            //遍历服务实例列表
            for (ServiceInstance instance : instances) {
                log.info("服务实例:id={},host={},port={},uri={}", instance.getServiceId(), instance.getHost(), instance.getPort(), instance.getUri());
            }
        }
        return discoveryClient;
    }
    //定义一个方法，添加member对象到数据库
    @PostMapping("/member/consumer/save")
    public Result<Member> save(Member member) {
        log.info("member_service_consumer member={}", member);
        /*参数说明：
            1、完整的url : MEMBER_SERVICE_PROVIDER_URL + "/member/save" => http://localhost:10000/member/save
            2、member : 就是通过 restTemplate 发出的post请求携带数据(对象).
              注：restTemplate底层会将请求的member信息封装成json对象，
                 因此 member对象需要实现序列化接口 并且 提供微服务接口接收member对象时使用 @RequestBody注解。
            3、Result.class: 返回对象类型
            4、这里通过 restTemplate 调用服务提供模块的接口, 就是一个远程调用 RPC
         */
        return restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL
                + "/member/save", member, Result.class);
    }

    //定义一个方法，根据传入的id查询对应的member对象
    @GetMapping("/member/consumer/query/{id}")
    public Result<Member> queryMemberById(@PathVariable("id") Long id) {

        return restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL
                + "/member/query/" + id, Result.class);
    }

}
